
import UIKit
import CommonCrypto

extension String {
    
    public var length: Int {
        self.count
    }
    
    public subscript (i: Int) -> String {
        self[i ..< i + 1]
    }
    
    public func substring(fromIndex: Int) -> String {
        self[min(fromIndex, length) ..< length]
    }
    
    public func substring(toIndex: Int) -> String {
        self[0 ..< max(0, toIndex)]
    }
    
    public subscript (r: Range<Int>) -> String {
        let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)), upper: min(length, max(0, r.upperBound))))
        let start = index(startIndex, offsetBy: range.lowerBound)
        let end = index(start, offsetBy: range.upperBound - range.lowerBound)
        return String(self[start ..< end])
    }
    
    /// range转换为NSRange
    public func nsRange(from range: Range<String.Index>) -> NSRange {
        NSRange(range, in: self)
    }
    
    public func toRange(range: NSRange) -> Range<String.Index>{
        let startIndex = self.index(self.startIndex, offsetBy: range.location)
        let endIndex = self.index(startIndex, offsetBy: range.length)
        return startIndex..<endIndex
    }
    
    public var md5:String {
        let utf8 = cString(using: .utf8)
        var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
        CC_MD5(utf8, CC_LONG(utf8!.count - 1), &digest)
        return digest.reduce("") { $0 + String(format:"%02X", $1) }
    }
    public var toDictionary:[String:Any]? {
        convertStringToDictionary()
    }
    public func convertStringToDictionary() -> [String:Any]? {
      if let data = data(using: String.Encoding.utf8) {
        do {
          return try JSONSerialization.jsonObject(with: data, options: [JSONSerialization.ReadingOptions.init(rawValue: 0)]) as? [String:AnyObject]
        } catch let error as NSError {
          print(error)
        }
      }
      return nil
    }
    
    public func formatWithUnit(places: Int16 = 1) -> String {
        guard let temp = Double(self) else{return "0"}
        
        let item = temp.format(grads: Double.TenThousandGrads)
        return item.value.truncate(places: places) + item.unit
    }
    
    public func mPrint() {
        print(self)
    }
    
    // 获取文本长度
    public func calculateTextLength(font:UIFont)->CGFloat{
        if self.count == 0 {
            return 0.0
        }
        let attributes  = [NSAttributedString.Key.font:font]
        let option      = NSStringDrawingOptions.usesLineFragmentOrigin
        let rect:CGRect = self.boundingRect(with: CGSize(width: CGFloat.infinity, height: CGFloat.infinity), options: option, attributes: attributes, context: nil)
        return rect.size.width
    }
    
    public static func isPhoneNumber(phone:String) ->Bool{
        //手机号以13-19[0-9]开头，八个 \d 数字字符
        let pattern = "^(([1-9][0-9][0-9]))\\d{8}$"
        return phone.regular(pattern: pattern)
    }
    
    // 安全的手机号显示
    public static func safeShowMobile(mobile:String) ->String{
        guard mobile.length >= 11 else {
            return mobile
        }
        return mobile.substring(toIndex: 3)+"****"+mobile.substring(fromIndex: 7)
    }
    
    // 安全的名字显示
    public static func safeShowUserName(name:String) -> String{
        guard name.length >= 1 else {
            return name
        }
        var ret = name.substring(toIndex: 1)
        for _ in 1..<name.length {
            ret.append("*")
        }
        return ret
    }
    
    // 安全的身份证显示
    public static func safeShowString(str:String, pre:Int, suf:Int, safeLength:Int? = nil) ->String{
        guard str.length > (pre+suf) else {
            return str
        }
        var ret = str.substring(toIndex: pre)
        let length = safeLength ?? str.length-(pre+suf)
        for _ in 0..<length {
            ret.append("*")
        }
        ret.append(str.substring(fromIndex: str.length-suf))
        return ret
    }
    
    public var isValidEmail: Bool {
        let emailRegex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
        return regular(pattern: emailRegex)
    }
    
    // 正则校验
    public func regular(pattern:String) -> Bool{
        return NSPredicate(format:"SELF MATCHES %@", pattern).evaluate(with: self)
    }
}

extension String{
    /// 富文本设置 字体大小 行间距 字间距
    public func attributedString(font: UIFont, textColor: UIColor, lineSpaceing: CGFloat, wordSpaceing: CGFloat) -> NSAttributedString {
        
        let style = NSMutableParagraphStyle()
        style.lineSpacing = lineSpaceing
        
        let attributes = [
            NSAttributedString.Key.font             : font,
            NSAttributedString.Key.foregroundColor  : textColor,
            NSAttributedString.Key.paragraphStyle   : style,
            NSAttributedString.Key.kern             : wordSpaceing]
        
        as [NSAttributedString.Key : Any]
        let attrStr = NSMutableAttributedString.init(string: self, attributes: attributes)
        
        return attrStr
    }
}

extension Double {
    
    public typealias Grads = (value: Double, units: [String])
    public static let TenThousandGrads = (value: 10000.0, units: ["","万","亿"])
    public static let ThousandGrads = (value: 1000.0, units: ["","K","M","G","T"])
    public static let MemorySizeGrads = (value: 1024.0, units: ["B","KB","M","G","T"])

    /// 截取长度 eg. 1.1001  => 1.1
    public func truncate(places : Int16,roundingMode: NSDecimalNumber.RoundingMode = .up)-> String {
        let handler = NSDecimalNumberHandler(roundingMode: roundingMode,
                                          scale: places,
                                          raiseOnExactness: false,
                                          raiseOnOverflow: false,
                                          raiseOnUnderflow: false,
                                          raiseOnDivideByZero: true)
        let value = NSDecimalNumber(value: self).adding(NSDecimalNumber(value: 0), withBehavior: handler)
        return "\(value)"
    }
    
    
    /// 数值转换  eg. 11000  => 1.1万
    /// - Parameters:
    ///   - grads: 梯度；分度;
    ///   - gradsUnits: 梯度；分度; 对应单位
    ///   - index: 进位
    /// - Returns: value：进位后的值
    public func format(grads:Grads,
                index: Int = 0) -> (value:Double,unit:String) {
        if grads.value > 0 ,
           self > grads.value ,
           index < (grads.units.count - 1) {
            return (self / grads.value).format(grads: grads,index: index + 1)
        }
        else {
            return (self,grads.units[safe:index] ?? grads.units.first ?? "")
        }
    }
}

extension String {
    
    public typealias AttributedStringMsg = (attri:NSMutableAttributedString,size:CGSize,htmlStr: String)
    
    public func htmlAttributed() throws -> NSMutableAttributedString? {
        guard let data = data(using: String.Encoding.utf8, allowLossyConversion: true) else {
            return nil
        }
        
        return try NSMutableAttributedString(data: data,
                                             options: [.documentType: NSAttributedString.DocumentType.html,
                                                       .characterEncoding: String.Encoding.utf8.rawValue],
                                             documentAttributes: nil)
    }
}

extension Double {
    // 移除小数点后无效的0
    public func correct(format: String? = nil) -> String? {
        if (fmod(self, 1)==0) { //无有效小数位
            return String(format: "%.0f", self)
        } else if let format = format {//如果有两位或以上小数点
            return String(format: format, self)
        }
        else {
            return "\(self)"
        }
    }
}

extension String {
    // 移除小数点后无效的0
    public func correct(format: String? = nil) -> String? {
        return Float(self)?.correct(format: format)
    }
}

extension Float {
    // 移除小数点后无效的0
    public func correct(format: String? = nil) -> String? {
        return Double(self).correct(format: format)
    }
}

public extension String {
    /// 编码字符串，使其适合用于 URL 中（支持阿拉伯文、中文、特殊字符等）
    var fixedArabicURL: String {
        return self.addingPercentEncoding(
            withAllowedCharacters:
                .alphanumerics
                .union(.urlPathAllowed)
                .union(.urlHostAllowed)
        ) ?? self
    }
    
    /// 将 URL 编码字符串解码为原始字符串
    var decodedFromURLEncoding: String {
        return self.removingPercentEncoding ?? self
    }
    
    /// 从外到内解码，直到变成一个合法的 URL 组件（不再含非法字符）
    var decodedUntilURLSafe: String {
        var result = self
        var previous: String
        let allowed = CharacterSet.alphanumerics
            .union(.urlPathAllowed)
            .union(.urlHostAllowed)

        repeat {
            previous = result
            let decoded = result.removingPercentEncoding ?? result

            // 如果解码后的字符串仍然只包含 URL-safe 字符，就返回
            if decoded.unicodeScalars.allSatisfy({ allowed.contains($0) }) {
                return decoded
            }

            result = decoded
        } while result != previous

        return result
    }
    
    func isURLEncodedAccurate(_ string: String) -> Bool {
        guard let decoded = string.removingPercentEncoding else { return false }
        return string != decoded && decoded.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) != string
    }
}

public extension String {
    @inlinable var isNotEmpty: Bool { !isEmpty }
}

public extension String {
    /// 格式化内容
    static func formatMessage(_ message: Any?) -> String {
        guard let message = message else { return "" }
        if let string = message as? String {
            return string
        } else if let dictionary = message as? [String: Any] {
            return formatJSON(dictionary)
        } else if let array = message as? [Any] {
            return array.compactMap { $0 }.formatMessage()
        } else if let object = message as? Codable, let dic = object.toJson() {
            return formatMessage(dic)
        }
        
        return ""  // 返回一个默认的字符串表示不支持的类型
    }
    /// 格式化内容
    static func formatJSON(_ object: Any?) -> String {
        guard let object = object else { return "Invalid JSON" }
        let cleaned = NSObject.recursivelyUnwrap(object)
        guard let jsonData = try? JSONSerialization.data(withJSONObject: cleaned, options: [.prettyPrinted, .sortedKeys]),
              let jsonString = String(data: jsonData, encoding: .utf8) else {
            return "Invalid JSON"
        }
        return jsonString
    }
}

public extension Dictionary {
    /// 格式化内容
    func formatMessage() -> String {
        return String.formatMessage(self)
    }
}

public extension Array {
    /// 格式化数组内容，每个元素占一行，并在每两个元素间插入换行
    func formatMessage() -> String {
        return self.compactMap { $0 }
            .compactMap { String.formatMessage($0) } // 递归格式化每个元素
            .enumerated()
            .map { index, element in
                index % 2 == 0 && index != 0 ? "\n\n\(element)" : element
            }
            .joined(separator: "\n\n")
    }
}

public extension String {
    func attributedString(_ attrs: [NSAttributedString.Key : Any],pattern: String) -> NSMutableAttributedString {
        return NSMutableAttributedString(string: self).addAttributes(attrs, pattern: pattern)
    }
    
    // 添加专门的正则表达式替换方法（解决核心问题）
    func replacing(regex pattern: String, with replacement: String, options: NSRegularExpression.Options = []) -> String {
        guard !pattern.isEmpty else { return self }
        
        do {
            // 创建正则表达式
            let regex = try NSRegularExpression(pattern: pattern, options: options)
            let nsString = self as NSString
            // 执行正则替换
            let result = regex.stringByReplacingMatches(
                in: self,
                options: [],
                range: NSRange(location: 0, length: nsString.length),
                withTemplate: replacement
            )
            return result
        } catch {
            print("正则表达式错误: \(error.localizedDescription)")
            return self
        }
    }
}

public extension String {
    public enum ZMPattern : String {
        case number = "[-+]?\\d+"
        // 处理分数分子（如 5/10 的 5）
        case fractionNumerator = "([-+]?\\d+)(?=(?:/|\\/)[0-9]+)"
        
        case episode = "^(.*?\\d+)"
    }
    
    func attributedString(color: UIColor = UIColor(0xFF2755),pattern: String) -> NSMutableAttributedString? {
                
        guard let regex = try? NSRegularExpression(pattern: pattern, options: []),
              let match = regex.firstMatch(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count)) else {
            return nil
        }
        let attributedT = NSMutableAttributedString(string: self)
        attributedT.addAttribute(.foregroundColor, value: color, range: match.range)
        return attributedT
    }
}

public extension NSMutableAttributedString {
    
    func addAttributes(_ attrs: [NSAttributedString.Key : Any],pattern: String) -> Self {
        let text = self.string
        if let regex = try? NSRegularExpression(pattern: pattern) {
            regex.enumerateMatches(in: text, range: NSRange(location: 0, length: text.length)) { match, _, _ in
                guard let match = match else { return }
                let range = match.range
                addAttributes(attrs, range: range)
            }
        }
        return self
    }
}


import SwiftUI

@available(iOS 15, *)
public extension String {
    /// 将字符串转换为富文本，为开头到第一个数字结尾的部分设置指定颜色
    /// - Parameter color: 要设置的颜色
    /// - Returns: 处理后的 AttributedString
    func toEpisodeAttributedString(color: Color?) -> AttributedString {
        let pattern = "^(.*?\\d+)" // 匹配开头到第一个数字结尾的部分
        var attributedText = AttributedString(self) // 将当前字符串转为 AttributedString
        
        // 查找正则匹配的范围
        if let range = attributedText.range(of: pattern, options: .regularExpression), let color = color {
            attributedText[range].foregroundColor = color // 为匹配范围设置颜色
        }
        
        return attributedText
    }
}
